/**
    Data Types

    this are all of the custom data types that are used by the ERD applicaiton

    erdTable - these are the database tables
    erdColumns - all of the cols with in a table
    erdConnection - the connection objects show the relationships

*/

// globals to the application

var erdTableCount = 0;
var erdTables = [];
var erdConns = [];
var xmlDoc;


// connection object definition

/**
@function {MyClass} erdConnection - a structure to hold the connection objects
@param {string} name - name of the connection object
@param {object} fromCol - a valid erdColumn object to draw connection from
@param {object} toCol - a valid erdColumn object to draw connection to
*/
function erdConnection(name, fromCol, fromSide, toCol, toSide) {
    this.name = name;
    this.from = fromCol;
    this.fromSide = fromSide;
    this.to = toCol;
    this.toSide = toSide;
}

/**
@function {void} drawToContext - this will draw the connection object to the canvas
@param {object} context - the canvas 2d drawing context
*/
erdConnection.prototype.drawToContext = function (context) {
    //console.log("draw conn " + this.from);
    var startX, startY;
    var endX, endY;
    var lenC = 10;
    
    if (this.fromSide == "r") {
        startX = this.from.x + 150;
    }
    else {
        startX = this.from.x;
    }
    startY = this.from.y;

    if (this.toSide == "r") {
        endX = this.to.x + 150;
    }
    else {
        endX = this.to.x;
    }
    endY = this.to.y;

    context.moveTo(startX, startY);
    if (this.fromSide == "r") {
        context.lineTo(startX + lenC, startY);
    }
    else {
        context.lineTo(startX - lenC, startY);
    }

    if (this.toSide == "r") {
        context.lineTo(endX + lenC, endY);
    }
    else {
        context.lineTo(endX - lenC, endY);
    }
    context.lineTo(endX, endY); // connect to right hand side

    context.strokeStyle = "#000";
    context.lineWidth = 1.5;
    context.stroke();
}



// column object definition

/**
@function {MyClass} erdColumn - a structure to hold the column types
@param {int} id - the int number of the column
@param {string} name - name of the table
@param {string} dataType - database type value
@param {bool} isVisible - true if you can see the column
@param {double} posX - initial x position of table in the canvas
@param {double} posY - initial y position of table in the canvas
@returns object with MyClass structures
*/
function erdColumn(id, name, dataType, isVisible, posX, posY) {
    // set the public properties
    this.id = id;
    this.name = name;
    this.dataType = dataType;
    this.isVisible = isVisible;
    this.x = posX;
    this.y = posY;
}

/**
@function {void} updatePosition - sets the x, y position of the object
@param {double} newX - new x pos relative within the canvas
@param {double} newY - new y pos relative within the canvas
*/
erdColumn.prototype.updatePosition = function (newX, newY) {
    this.x = newX;
    this.y = newY;
}



// table object definition

/**
@function {MyClass} erdTable
@param {string} name - name of the table
@param {double} posX - initial x position of table in the canvas
@param {double} posY - initial y position of table in the canvas
@returns object with MyClass structures
*/
function erdTable(name, posX, posY) {
    // public member definition
    this.x = posX;
    this.y = posY;
    this.name = name;

    this.color = "#1c361a"; //  "#292966";

    this.radius = 31; // this is old code and needs to be pulled out
    this.width = 150;
    this.height = 200;

    this.centerX = this.x + (this.width * 0.5);
    this.centerY = this.y + (this.height * 0.5);

    this.cols;
    this.cols = [];

    this.totalCols = 0;

    //private members
    var calcWidth;
    var calcHeight;

    // calculated height...
    this.__defineGetter__("calcHeight", function () { return calcHeight });
    this.__defineSetter__("calcHeight", function (val) { calcHeight = val });

    // calculated width...
    this.__defineGetter__("calcWidth", function () { return calcWidth });
    this.__defineSetter__("calcWidth", function (val) { calcWidth = val });

}

/**
@function {void} loadColumns - loads all of the columns from the xml file
*/
erdTable.prototype.loadColumns = function () {
    // try and load columns...
    this.cols = xmlGetColumns(this.name, this.x, this.y);
    this.totalCols = this.cols.length;

    //console.log("col count" + this.totalCols);

    // set the calulated width and height
    this.calcHeight = this.totalCols * 13;
    this.calcWidth = 150;

    // set the new width and height
    this.height = this.calcHeight + 18;
    this.width = this.calcWidth;
}

/**
@function {void} addColumn - loads single column from the xml file
@param {string} column - the name of the column to load
*/
erdTable.prototype.addColumn = function (column) {
    this.totalCols++;
    this.cols.push(column);
}

/**
@function {bool} hitTest - checks for a mouse click within objects bounds
@param {double} hitX - mouses x pos
@param {double} hitY - mouses y pos
*/
erdTable.prototype.hitTest = function (hitX, hitY) {
    return ((hitX > this.x) && (this.x < this.x + this.width) &&
            (hitY > this.y) && (this.y < this.y + this.height));
}

/**
@function {void} updatePosition - sets the x, y position of the object
@param {double} newX - new x pos relative within the canvas
@param {double} newY - new y pos relative within the canvas
*/
erdTable.prototype.updatePosition = function (newX, newY) {
    // i need a way to update everything when a table moves around..
    this.x = newX;
    this.y = newY;

    // update the columns...
    for (var i = 0; i < this.cols.length; i++) {
        this.cols[i].updatePosition(this.x, (this.y + 26) + (i * 13));
    }
}

/**
@function {void} drawToContext - this will draw the table object to the canvas
@param {object} context - the canvas 2d drawing context
*/
erdTable.prototype.drawToContext = function (context) {
    // draw the background of the table
    context.beginPath();
    context.fillStyle = this.color;
    context.fillRect(this.x, this.y, this.width, this.height);
    context.closePath();
    context.fill();

    var m = context.measureText(this.name);
    var w = m.width;

    // draw table name
    context.font = "bold 11px verdana";
    context.fillStyle = "#fff";
    context.fillText(this.name, this.x + 5, this.y + 12, this.width);

    // draw columns
    context.font = "normal 10px courier new";
    var startY = this.y + 26;
    for (var i = 0; i < this.totalCols; i++) {
        context.fillStyle = (isOdd(i) == true) ? "#b4d1b2" : "#fff"; // #d1d4eb blue highlite

        // calc the columns rect pos
        this.cols[i].posX = this.x;
        this.cols[i].posY = (startY + (i * 13)) - 10;

        context.fillRect(this.cols[i].posX, this.cols[i].posY, this.width, 13);
        context.fill();
        context.fillStyle = "#000"; // black text
        context.fillText(this.cols[i].name, this.x + 2, startY + (i * 13), this.width);
    }

    // draw outline
    context.strokeStyle = "#000";
    context.lineWidth = 1.5;
    context.strokeRect(this.x, this.y, this.width, this.height);
    context.stroke();
}



// global methods

/**
@function {Alert} getAllProperties - gets all the properties of passed in object and displays in an alert
@param {object} obj - the object to pull props from
*/
function getAllProperties(obj) {
    var properties = '';
    for (property in obj) {
        properties += '\n' + property;
    }
    alert('Properties of object:' + properties);
}

/**
@function {bool} isOdd - returns true if a number is odd, false otherwise
@param {number} num - the numeric value to test
*/
function isOdd(num) { return num % 2; }

/**
@function {Array} myUcase - converst all the array element strings to upper case
*/
Array.prototype.myUcase = function () {
    for (var i = 0; i < this.length; i++) {
        this[i] = this[i].toUpperCase();
    }
}

/**
@function {void} testDataTypes - a method used to test the data types object
*/
function testDataTypes() {
    var c = document.getElementById("myCanvas");
    var ctx = c.getContext("2d");

    init();

    // test method only, not used by app
    function init() {
        // load up the base tables
        loadBaseTables();
        console.log("loaded base tables");
        erdTables[0].drawToContext(ctx);
    }

    // test method only, not used by app
    function loadBaseTables() {
        erdTableCount++;
        var temp = new erdTable("Contact", 100, 50);
        temp.loadColumns();
        erdTables.push(temp);
    }

    // test method only, not used by app
    function addTestTable() {
        erdTableCount++;

        var temp = new erdTable("contact", 100, 50);
        temp.addColumn("CONT_ID");
        temp.addColumn("CONTACT_NAME");
        temp.addColumn("PERSON_ORG_CODE");
        temp.addColumn("X_CCID");
        temp.addColumn("SINCE_DT");

        erdTables.push(temp);
        console.log("added");
    }
}


